﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;

namespace Workflows.Components.Rules
{
    /// <summary>
    /// getting rule nodes from assemblies, image size changed to 20x20 
    /// </summary>
    public class RuleNodeFactory
    {
        /// <summary>
        /// get implemented DeclarativeRuleCondition from bin dir
        /// </summary>
        /// <returns></returns>
        public static List<RuleNodeDataBase> GetRuleConditionNodes()
        {
            List<RuleNodeDataBase> conditions = new List<RuleNodeDataBase>();
            List<Assembly> assemblies = RuleNodeFactory.GetManagedAssemblies();
            foreach (Assembly assem in assemblies)
            {
                Type[] types = assem.GetTypes();
                foreach (Type type in types)
                {
                    if (type.IsSubclassOf(typeof(RuleNodeDataBase)))
                    {
                        RuleNodeDataBase ruleNodeData = (RuleNodeDataBase) Activator.CreateInstance(type);
                        if(ruleNodeData.RuleNodeType==RuleNodeType.Conditional)
                        {
                            conditions.Add(ruleNodeData);
                        }
                    }
                }
            }
            return conditions;
        }

        /// <summary>
        /// get implemented RuleEffect from bin dir
        /// </summary>
        /// <returns></returns>
        public static List<RuleNodeDataBase> GetRuleEffectNodes()
        {
            List<RuleNodeDataBase> effects = new List<RuleNodeDataBase>();
            List<Assembly> assemblies = RuleNodeFactory.GetManagedAssemblies();
            foreach (Assembly assem in assemblies)
            {
                Type[] types = assem.GetTypes();
                foreach (Type type in types)
                {
                    if (type.IsSubclassOf(typeof(RuleNodeDataBase)))
                    {
                        RuleNodeDataBase ruleNodeData = (RuleNodeDataBase) Activator.CreateInstance(type);
                        if (ruleNodeData.RuleNodeType == RuleNodeType.Effect)
                        {
                            effects.Add(ruleNodeData);
                        }
                    }
                }
            }
            return effects;
        }

        /// <summary>
        /// get implemented RuleComponentOutput from bin dir 
        /// </summary>
        /// <returns></returns>
        public static List<RuleNodeDataBase> GetRuleOutputNodes()
        {
            List<RuleNodeDataBase> outputs = new List<RuleNodeDataBase>();
            List<Assembly> assemblies = RuleNodeFactory.GetManagedAssemblies();
            foreach (Assembly assem in assemblies)
            {
                Type[] types = assem.GetTypes();
                foreach (Type type in types)
                {
                    if (type.IsSubclassOf(typeof(RuleNodeDataBase)))
                    {
                        RuleNodeDataBase ruleNodeData = (RuleNodeDataBase) Activator.CreateInstance(type);
                        if (ruleNodeData.RuleNodeType == RuleNodeType.Output)
                        {
                            outputs.Add(ruleNodeData);
                        }
                    }
                }
            }
            return outputs;
        }

        /// <summary>
        /// get implemented RuleAction from bin dir 
        /// </summary>
        /// <returns></returns>
        public static List<RuleNodeDataBase> GetRuleActionNodes()
        {
            List<RuleNodeDataBase> actions = new List<RuleNodeDataBase>();
            List<Assembly> assemblies = RuleNodeFactory.GetManagedAssemblies();
            foreach (Assembly assem in assemblies)
            {
                Type[] types = assem.GetTypes();
                foreach (Type type in types)
                {
                    if (type.IsSubclassOf(typeof(RuleNodeDataBase)))
                    {
                        RuleNodeDataBase ruleNodeData = (RuleNodeDataBase) Activator.CreateInstance(type);
                        if (ruleNodeData.RuleNodeType == RuleNodeType.Action)
                        {
                            actions.Add(ruleNodeData);
                        }
                    }
                }
            }
            return actions;
        }

        #region reflection
        /// <summary>
        /// get .NET managed assemblies from bin folder
        /// </summary>
        /// <returns></returns>
        private static List<Assembly> GetManagedAssemblies()
        {
            string binFolderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            DirectoryInfo binDirInfo = new DirectoryInfo(binFolderPath);
            FileInfo[] dllInfos = binDirInfo.GetFiles("*.dll", SearchOption.TopDirectoryOnly);
            List<Assembly> assemblies = new List<Assembly>();
            foreach (FileInfo fileInfo in dllInfos)
            {
                try
                {
                    Assembly assem = Assembly.LoadFrom(fileInfo.FullName);
                    assemblies.Add(assem);
                }
                catch
                {
                    Console.WriteLine("Unable to load " + fileInfo.Name + " into assembly");
                }
            }
            return assemblies;
        }
        #endregion
    }
}
